#include "UP_GPIO.h"
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*!
    \brief    GPIO初始化
    \param[in]  pin: 引脚名称，如PA0、PB1、PC2等
    \param[in]  mode: 引脚模式
        \arg    0：推挽输出模式
        \arg    1：开漏输出模式
        \arg    2：浮空/高阻输入
        \arg    3：上拉输入
        \arg    4: 下拉输入
        \arg    5: 模拟
    \param[out] none
    \retval     none
*/
void GPIO_Init(UP_GPIO uc_gpio, uint8_t mode)
{
    // enable clock
    rcu_periph_clock_enable(uc_gpio.rcu_gpio);

    switch (mode) {
        case 0: // 推挽输出模式
            // config gpio mode
            gpio_mode_set(uc_gpio.port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, uc_gpio.pin);
            // set gpio output type as push-pull
            gpio_output_options_set(uc_gpio.port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, uc_gpio.pin);
            break;
        case 1: // 开漏输出模式
            // config gpio mode
            gpio_mode_set(uc_gpio.port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, uc_gpio.pin);
            // set gpio output type as push-pull
            gpio_output_options_set(uc_gpio.port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, uc_gpio.pin);
            break;
        case 2: // 浮空/高阻输入
            // config gpio mode
            gpio_mode_set(uc_gpio.port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, uc_gpio.pin);
            break;
        case 3: // 上拉输入
            // config gpio mode
            gpio_mode_set(uc_gpio.port, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, uc_gpio.pin);
            break;
        case 4: // 下拉输入
            // config gpio mode
            gpio_mode_set(uc_gpio.port, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, uc_gpio.pin);
            break;
        case 5: // 模拟
            // config gpio mode
            gpio_mode_set(uc_gpio.port, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, uc_gpio.pin);
            break;
        default:
            break;
    }
}

void GPIO_Init_AF(UP_GPIO uc_gpio, uint32_t af)
{
    UP_GPIO_PARAMS params = {
        .pull_up_down = GPIO_PUPD_NONE,
        .otype        = GPIO_OTYPE_PP
    };
    GPIO_Init_AF_with_config(uc_gpio, af, &params);
}
void GPIO_Init_AF_with_config(UP_GPIO uc_gpio, uint32_t af, UP_GPIO_PARAMS *params)
{
    // enable clock
    rcu_periph_clock_enable(uc_gpio.rcu_gpio);
    gpio_af_set(uc_gpio.port, af, uc_gpio.pin); //
    gpio_mode_set(uc_gpio.port, GPIO_MODE_AF, params->pull_up_down, uc_gpio.pin);
    gpio_output_options_set(uc_gpio.port, params->otype, GPIO_OSPEED_50MHZ, uc_gpio.pin);
}

unsigned char GPIO_Get(UP_GPIO uc_gpio)
{
    return gpio_input_bit_get(uc_gpio.port, uc_gpio.pin);
}

void GPIO_Set(UP_GPIO uc_gpio, uint8_t value)
{
    gpio_bit_write(uc_gpio.port, uc_gpio.pin, value);
}

void GPIO_Toggle(UP_GPIO uc_gpio)
{
    gpio_bit_write(uc_gpio.port, uc_gpio.pin, (bit_status)(1 - gpio_input_bit_get(uc_gpio.port, uc_gpio.pin)));
}
void GPIO_key_scan(UP_GPIO uc_gpio)
{
    if (!GPIO_Get(uc_gpio)) {
        delay_1ms(20);
        if (!GPIO_Get(uc_gpio)) {
            // on_key_up();
            while (!GPIO_Get(uc_gpio))
                ;
            on_key_down();
        }
    }
}